package org.noootsab.gae.games.tzaar.model;

import com.google.appengine.api.datastore.*;
import com.google.appengine.api.datastore.Key;
import org.json.simple.*;
import org.json.simple.parser.*;
import org.noootsab.gae.games.tzaar.service.*;

import javax.jdo.*;
import javax.jdo.Query;
import javax.jdo.annotations.*;
import java.io.*;

/**
 * User: sandy
 * Date: 11-avr.-2010
 * Time: 15:29:04
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Statistic implements Externalizable {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    @Persistent
    private Key player;

    @Persistent
    private int won = 0;

    @Persistent
    private int lost = 0;

    @Persistent
    private Text scores;

    public Statistic() {
        scores = null;
    }

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public Key getPlayer() {
        return player;
    }

    public void setPlayer(Key player) {
        this.player = player;
    }

    public int getWon() {
        return won;
    }

    public void setWon(int won) {
        this.won = won;
    }

    public int getLost() {
        return lost;
    }

    public void setLost(int lost) {
        this.lost = lost;
    }

    public Text getScores() {
        return scores;
    }

    public void setScores(Text scores) {
        this.scores = scores;
    }

    public void wonAgainst(Key against) {
        won++;
        updateScore(against, 1);
    }

    public void lostAgainst(Key against) {
        lost++;
        updateScore(against, -1);
    }

    private void updateScore(Key against, Integer inc) {
        String scoresString;
        if (scores == null) {
            scoresString = "[]";
        } else {
            scoresString = scores.getValue();
        }

        JSONArray scoresJson = null;
        try {
            scoresJson = (JSONArray)new JSONParser().parse(new StringReader(scoresString));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        String email = null;
        try {
            PersistenceManager persistenceManager = PersistenceManagerFactoryHelper.get().getPersistenceManager();
            Query query = persistenceManager.newQuery("select email from " + Player.class.getName() +" where key == :k");
            query.setUnique(true);
            Email emailE = (Email) query.execute(against);
            email = emailE.getEmail();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (email == null) {
            throw new RuntimeException("Email is null???");
        }

        JSONObject existing = null;
            for (Object o : scoresJson) {
                JSONObject jsonO = (JSONObject) o;
                Object opp = jsonO.get("opponent");
                if (opp != null && email.equals(opp)) {
                    existing = jsonO;
                    break;
                }
            }
            if (existing == null) {
                existing = new JSONObject();
                existing.put("opponent", email);
                existing.put("w", 0L);
                existing.put("l", 0L);
                scoresJson.add(existing);
            }

            String index = inc > 0 ? "w" : "l";
            existing.put(index, ((Long)existing.get(index)) + Math.abs(inc));

            setScores(new Text(scoresJson.toString()));
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        //will never been called
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        if (key != null) {
            out.writeObject(KeyFactory.keyToString(key));
        }
        out.writeObject(KeyFactory.keyToString(player));
        out.writeObject(won);
        out.writeObject(lost);
        if (scores == null) {
            out.writeObject("{\"empty\":\"true\"}");
        } else {
            out.writeObject(scores.getValue());
        }
    }
}
